package com.tjmc.nsia.core.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tjmc.nsia.core.dao.entity.NsiaExam;
import com.tjmc.nsia.core.dao.entity.NsiaExamCategory;
import com.tjmc.nsia.core.dao.entity.NsiaExamSubmit;
import com.tjmc.nsia.core.dao.entity.NsiaUser;
import com.tjmc.nsia.core.dao.mapper.NsiaExamCategoryMapper;
import com.tjmc.nsia.core.dao.mapper.NsiaExamMapper;
import com.tjmc.nsia.core.dao.mapper.NsiaExamSubmitMapper;
import com.tjmc.nsia.core.dto.resp.NsiaExamCategoryExtend;
import com.tjmc.nsia.core.dto.resp.NsiaExamQuestion;
import com.tjmc.nsia.core.dto.resp.NsiaExamQuestionAnswer;
import com.tjmc.nsia.core.dto.resp.NsiaExamQuestionOption;
import com.tjmc.nsia.core.service.NsiaExamService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2024/07/10
 */
@Service
public class NsiaExamServiceImpl extends ServiceImpl<NsiaExamMapper, NsiaExam> implements NsiaExamService {

    @Value("${nsia.file.upload.path}")
    private String fileUploadPath;

    @Autowired
    private NsiaExamCategoryMapper nsiaExamCategoryMapper;

    @Autowired
    private NsiaExamMapper nsiaExamMapper;

    @Autowired
    private NsiaExamSubmitMapper nsiaExamSubmitMapper;


    @Override
    public List<NsiaExamCategoryExtend> getAllCategories() {
        List<NsiaExamCategory> categories = nsiaExamCategoryMapper.selectList(null);
        List<NsiaExamCategoryExtend> categoryExtends = null;
        if(!CollectionUtil.isEmpty(categories)) {
            categoryExtends = categories.stream().map(category -> {
                NsiaExamCategoryExtend categoryExtend = new NsiaExamCategoryExtend();
                BeanUtils.copyProperties(category, categoryExtend);
                categoryExtend.setExams(nsiaExamMapper.selectList(new QueryWrapper<NsiaExam>().eq("category_id", category.getId())));
                return categoryExtend;
            }).collect(Collectors.toList());
        }
        return categoryExtends;
    }

    @Override
    public List<NsiaExamQuestion> parseExamFile(String filePath) {
        ExcelReader reader = ExcelUtil.getReader(fileUploadPath + filePath);
        List<Map<String, Object>> readAll = reader.readAll();
        List<NsiaExamQuestion> examQuestions = new ArrayList<>();
        for (Map<String, Object> question : readAll) {
            NsiaExamQuestion examQuestion = new NsiaExamQuestion();
            examQuestion.setOptions(new ArrayList<>());
            for(String key:question.keySet()) {
                if("题型".equals(key)) {
                    if ("单选题".equals(question.get(key))) {
                        examQuestion.setType((byte) 1);
                    } else if ("多选题".equals(question.get(key))) {
                        examQuestion.setType((byte) 2);
                    } else if ("判断题".equals(question.get(key))) {
                        examQuestion.setType((byte) 3);
                    } else if ("填空题".equals(question.get(key))) {
                        examQuestion.setType((byte) 4);
                    }
                } else if("序号".equals(key)) {
                    examQuestion.setNo((Long) question.get(key));
                } else if("题目内容".equals(key)) {
                    examQuestion.setQuestion((String) question.get(key));
                } else if("答案".equals(key)) {
                    examQuestion.setAnswer((String) question.get(key));
                    if(examQuestion.getType() == 4) { //填空题
                        String[] answers = examQuestion.getAnswer().split("\\|");
                        if(!Objects.isNull(answers)) {
                            for(int i=0; i<answers.length; i++) {
                                NsiaExamQuestionOption nsiaExamQuestionOption = new NsiaExamQuestionOption();
                                nsiaExamQuestionOption.setKey(answers[i]);
                                examQuestion.getOptions().add(nsiaExamQuestionOption);
                            }
                        }
                    }
                } else if("分数".equals(key)) {
                    if(!Objects.isNull(question.get(key))) {
                        String pattern = "[^0-9.]";
                        String result = question.get(key).toString().replaceAll(pattern, "");
                        if(StringUtils.hasText(result)) {
                            examQuestion.setScore(Double.parseDouble(result));
                        } else {
                            examQuestion.setScore(0.0);
                        }
                    } else {
                        examQuestion.setScore(0.0);
                    }
                } else if(key.indexOf("选项") != -1 && ((String) question.get(key)).trim().length() > 0) {
                    String header = key.substring(key.indexOf("选项")+"选项".length()).trim().toUpperCase();
                    NsiaExamQuestionOption nsiaExamQuestionOption = new NsiaExamQuestionOption();
                    nsiaExamQuestionOption.setKey(header);
                    nsiaExamQuestionOption.setContext((String) question.get(key));
                    examQuestion.getOptions().add(nsiaExamQuestionOption);
                }
            }
            examQuestions.add(examQuestion);
        }
        return examQuestions;
    }

    @Override
    public double submit(NsiaUser nsiaUser, NsiaExamQuestionAnswer nsiaExamQuestionAnswer) {
        if(!Objects.isNull(nsiaUser) && !Objects.isNull(nsiaExamQuestionAnswer)) {
            NsiaExam nsiaExam = nsiaExamMapper.selectById(nsiaExamQuestionAnswer.getExamId());
            if(!Objects.isNull(nsiaExam)) {
                double score = this.computeScore(nsiaExamQuestionAnswer.getQuestions());
                NsiaExamSubmit nsiaExamSubmit = new NsiaExamSubmit();
                nsiaExamSubmit.setUsername(nsiaUser.getUsername());
                nsiaExamSubmit.setExamTitle(nsiaExam.getTitle());
                nsiaExamSubmit.setReplys(JSONObject.from(nsiaExamQuestionAnswer));
                nsiaExamSubmit.setScore(String.valueOf(score));
                nsiaExamSubmit.setUserId(nsiaUser.getId());
                nsiaExamSubmit.setExamId(nsiaExam.getId());
                nsiaExamSubmit.setSubmitTime(LocalDateTime.now());
                nsiaExamSubmitMapper.insert(nsiaExamSubmit);
                return score;
            }
        }
        return 0;
    }

    private double computeScore(List<NsiaExamQuestion> replys) {
        double score = 0;
        if(!CollectionUtil.isEmpty(replys)) {
            for(NsiaExamQuestion reply: replys) {
                if(StringUtils.hasText(reply.getReply())) {
                    byte type = reply.getType();
                    if(2 != type) {
                        if(reply.getReply().trim().equals(reply.getAnswer().trim()) && !Objects.isNull(reply.getScore())) {
                            score += reply.getScore();
                        }
                    } else {
                        String[] ss = reply.getReply().split("|||");
                        String[] as = reply.getAnswer().split("|||");
                        if(ArrayUtil.isNotEmpty(ss) && ArrayUtil.isNotEmpty(as) && ss.length == as.length) {
                            Set<String> sss = new HashSet<>();
                            sss.addAll(Arrays.asList(ss));
                            Set<String> ass = new HashSet<>();
                            ass.addAll(Arrays.asList(as));
                            if(sss.containsAll(ass) && ass.containsAll(sss) && !Objects.isNull(reply.getScore())) {
                                score += reply.getScore();
                            }
                        }
                    }
                }
            }
        }
        return score;
    }
}
